package java_learn.java_jinjie.Lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 卖票案例出现了线程安全问题
 * 解决线程安全问题的三种方案:使用Lock锁
 * java.util.concurrent.locks.Lock接口
 * Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。
 * Lock接口中的方法:
 * void lock()获取锁。
 * void unlock()  释放锁。
 * java.util.concurrent.locks.ReentrantLock implements Lock接口
 * <p>
 * <p>
 * 使用步骤:
 * 1.在成员位置创建一个ReentrantLock对象
 * 2.在可能会出现安全问题的代码前调用Lock接口中的方法lock获取锁
 * 3.在可能会出现安全问题的代码后调用Lock接口中的方法unlock释放锁
 *
 * @Author: 李浩然
 * @Date: 2020/12/18 2:58 下午
 */
public class RunnableSafeImpl implements Runnable {
    private int ticket = 100;
    //创建一个锁对象
    Lock l = new ReentrantLock();

    /**
     * 卖票
     */
    @Override
    public void run() {
        //判断票是否存在
        while (true) {
            l.lock();
            //同步代码块
            if (ticket > 0) {
                try {
                    Thread.sleep(10);
                    System.out.println(Thread.currentThread().getName() + "-->正在卖第" + ticket-- + "张票");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    //无论程序是否异常，锁都会释放
                    l.unlock();
                }
            }
        }
    }
}
